/*
 * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
 * http://docs.jquery.com/Plugins/Treeview
 *
 * Copyright (c) 2007 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
 *
 */

;(function($) {

	$.extend($.fn, {
		swapClass: function(c1, c2) {
			var c1Elements = this.filter('.' + c1);
			this.filter('.' + c2).removeClass(c2).addClass(c1);
			c1Elements.removeClass(c1).addClass(c2);
			return this;
		},
		replaceClass: function(c1, c2) {
			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
		},
		hoverClass: function(className) {
			className = className || "hover";
			return this.hover(function() {
				$(this).addClass(className);
			}, function() {
				$(this).removeClass(className);
			});
		},
		heightToggle: function(animated, callback) {
			animated ?
				this.animate({ height: "toggle" }, animated, callback) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
					if(callback)
						callback.apply(this, arguments);
				});
		},
		heightHide: function(animated, callback) {
			if (animated) {
				this.animate({ height: "hide" }, animated, callback);
			} else {
				this.hide();
				if (callback)
					this.each(callback);				
			}
		},
		prepareBranches: function(settings) {
			if (!settings.prerendered) {
				// mark last tree items
				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
				// collapse whole tree, or only those marked as closed, anyway except those marked as open
				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
			}
			// return all items with sublists
			return this.filter(":has(>ul)");
		},
		applyClasses: function(settings, toggler) {
			this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
				toggler.apply($(this).next());
			}).add( $("a", this) ).hoverClass();
			
			if (!settings.prerendered) {
				// handle closed ones first
				this.filter(":has(>ul:hidden)")
						.addClass(CLASSES.expandable)
						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
						
				// handle open ones
				this.not(":has(>ul:hidden)")
						.addClass(CLASSES.collapsable)
						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
						
	            // create hitarea
				this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
					var classes = "";
					$.each($(this).parent().attr("class").split(" "), function() {
						classes += this + "-hitarea ";
					});
					$(this).addClass( classes );
				});
			}
			
			// apply event to hitarea
			this.find("div." + CLASSES.hitarea).click( toggler );
		},
		treeview: function(settings) {
			settings = $.extend({
				cookieId: "treeview"
			}, settings);
			
			if (settings.add) {
				return this.trigger("add", [settings.add]);
			}

			function searchController(tree, control, input) {
				function handler() {
					isSearchToggle = true;
					return function() {
						search(tree, toggler, input);
						isSearchToggle = isProcessing;
						return false;
					};
					return exec;
				}
				$(control).click( handler() );
			}

			function search(object, toggler, input) {
				searchCount++;
				
				// clear last search
				if (searchCount > 1) {
					$(".searchYellow", object).removeClass("searchYellow");
					$(object).find("ul > li > ul").each(function(){
						$(this).parent().find(">.hitarea").each(function(){
							if ($(this).hasClass(CLASSES.collapsableHitarea)) {
								$(this).removeClass(CLASSES.collapsableHitarea).addClass(CLASSES.expandableHitarea);
								$(this).parent().removeClass(CLASSES.collapsable).addClass(CLASSES.expandable);
							}
							else if ($(this).hasClass(CLASSES.lastCollapsableHitarea)) {
								$(this).removeClass(CLASSES.lastCollapsableHitarea).addClass(CLASSES.lastExpandableHitarea);
								$(this).parent().removeClass(CLASSES.lastCollapsable).addClass(CLASSES.lastExpandable);
							}
						});
						$(this).hide();
					})
				}
				
				var content = jQuery.trim($(input).val());
				
				// filter empty string
				if (content == "") {
					$(input).val("");
					$(input).focus();
					alert('Please input search dept!');
					return false;
				} else {
					// filter number string
					for (var i = 0; i < content.length; i++) {
						if (numbers.indexOf(content.charAt(i)) == -1
							&& chars.indexOf(content.charAt(i)) == -1
							&& code.indexOf(content.charAt(i)) == -1) {
							break;
						}
					}
					if (i == content.length) {
						return false;
					}
				}
				
				/*
				$("a[name='treeNode']").each(function() {
					if ($(this).html().indexOf(content) != -1) {
						$(this).addClass("searchYellow");
						toggler.apply($(this).parent().children("div.hitarea:first"));
					}
				});
				return false;
				*/
				
				$(object).children().each(function(){
					foo(object.attr("id"), this, content, toggler)
				});
			}

			function foo(treeid, object, content, toggler)
			{
				$(object).find("ul:first>li").each(function(index){
					var div = $(this).find("div.hitarea:first").each(function(){
						foo(treeid, $(this).parent(), content, toggler);
						return this;
					});

					if ($(this).html().indexOf(content) != -1)
					{
						if ($(div).attr("tagName") != "DIV")// <li>
						{
							var span = $(this).find("a:first");
							if (span.html().indexOf(content) != -1)
							{
								span.addClass("searchYellow");
							}
							var branch = $(this).parents().parent();
							if (branch.parent().attr("id") == treeid)
							{
								//toggler.apply(branch.children("div.hitarea:first"));
								toggler.apply ( branch.children("div.hitarea:first").filter(function() {
									return $(this).parent(".expandable").length;
								}) );
							}
						}
						else// <div>
						{
							var span = $(this).find("a:first");
							if (span.html().indexOf(content) != -1)
							{
								span.addClass("searchYellow");
							}
							
							toggler.apply ( $(div).filter(function() {
								return $(this).parent(".expandable").length;
							}) );
							var branch = $(this).parents().parent();
							if (branch.parent().attr("id") == treeid)
							{
								toggler.apply ( branch.children("div.hitarea:first").filter(function() {
									return $(this).parent(".expandable").length;
								}) );
							}
							else
							{
								toggler.apply ( branch.children("div.hitarea:first").filter(function() {
									return $(this).parent(".expandable").length;
								}) );
								toggler.apply ( branch.children("div.hitarea:first").filter(function() {
									return $(this).parent(".lastExpandable").length;
								}) );								
							}
						}
					}
				});

				if ($(object).parent().attr("id") == treeid)
				{
					var span = $(object).find("a:first");
					if (span.html().indexOf(content) != -1)
					{
						span.addClass("searchYellow");
					}
				}
			}
		
			// handle toggle event
			function toggler() {
				$(this)
					.parent()
					// swap classes for hitarea
					.find(">.hitarea")
						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
					.end()
					// swap classes for parent li
					.swapClass( CLASSES.collapsable, CLASSES.expandable )
					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
					// find child lists
					.find( ">ul" )
					// toggle them
					.heightToggle( settings.animated, settings.toggle );
				
				if (!isProcessing) {
					isSearchToggle = isProcessing;
					$(this).async(tree);
				}
			}
			
			var tree = this;
			
			// add treeview class to activate styles
			this.addClass("treeview");
			
			// prepare branches and find all tree items with child lists
			var branches = this.find("li").prepareBranches(settings);
			
			branches.applyClasses(settings, toggler);
				
			// if control option is set, create the treecontroller and show it
			if ( settings.control ) {
				searchController(this, settings.control, settings.input);
				//$(settings.control).show();
			}
			
			return this.bind("add", function(event, branches) {
				$(branches).prev()
					.removeClass(CLASSES.last)
					.removeClass(CLASSES.lastCollapsable)
					.removeClass(CLASSES.lastExpandable)
				.find(">.hitarea")
					.removeClass(CLASSES.lastCollapsableHitarea)
					.removeClass(CLASSES.lastExpandableHitarea);
				$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
			});
		},
		async: function(tree) {
			var asyncNodeList;
			if (typeof(tree) == "undefined") {
				tree = this;
				asyncNodeList = $(".second", tree);
				isSearchToggle = true;
				isProcessing = true;
			} else {
				asyncNodeList = $(this).parent();
			}
			var len = asyncNodeList.size();
			var count = 0;
			var nodeId;
			
			asyncNodeList.each(function(i, item) {
				nodeId = $(item).children("a:first").attr("id");
				if (typeof(nodeId) == "undefined" || nodeId == null || nodeId == '') {
					count++;
					return false;
				} else {
					$(item).children("a:first").removeAttr("id");
				}
				$.ajax({
					type: "POST",
					url: "asyncDepartmentTreeViewAction.do?type=tile&nodeNo=" + nodeId,
					timeout: 20000,
					error: function() {
						count++;
						if (count == len) {
							isProcessing = false;
							$("#notice").hide();
							$("#searchbutton").removeAttr("disabled");
						}
					},
					success: function(responseText) {
						count++;
						if (count == len) {
							isProcessing = false;
							$("#notice").hide();
							$("#searchbutton").removeAttr("disabled");
						}
						if (jQuery.trim(responseText) == "") {
							return;
						}
						$(item).html($(item).html() + responseText);
						$("li:last-child", item).each(function(){
							if ($(this).hasClass("expandable")) {
								$(this).removeClass("expandable").addClass("lastExpandable");
								$(this).find("div.expandable-hitarea:first").removeClass("expandable-hitarea").addClass("lastExpandable-hitarea");
							} else {
								$(this).addClass("last");
							}
						});						
						$(tree).treeview({ add: item });
					},
					complete: function() {
						if (!isSearchToggle) {
							$(item)	// swap classes for hitarea
							.find(">.hitarea").swapClass(CLASSES.collapsableHitarea, CLASSES.collapsableHitarea).swapClass(CLASSES.lastCollapsableHitarea, CLASSES.lastCollapsableHitarea).end()
							// swap classes for parent li
							.swapClass(CLASSES.collapsable, CLASSES.collapsable).swapClass(CLASSES.lastCollapsable, CLASSES.lastCollapsable);
							$(item).children("ul:first").show();
						}
					}
				});
			});
		}
	});
	
	var searchCount = 0;
	
	var numbers = "0123456789";
	var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	var code = "~!@#$%^&*()_+`-={}[]:\";'<>?,./|\\";
	
	var isProcessing = false;
	var isSearchToggle = false;
	
	// classes used by the plugin
	// need to be styled via external stylesheet, see first example
	var CLASSES = $.fn.treeview.classes = {
		open: "open",
		closed: "closed",
		expandable: "expandable",
		expandableHitarea: "expandable-hitarea",
		lastExpandableHitarea: "lastExpandable-hitarea",
		collapsable: "collapsable",
		collapsableHitarea: "collapsable-hitarea",
		lastCollapsableHitarea: "lastCollapsable-hitarea",
		lastCollapsable: "lastCollapsable",
		lastExpandable: "lastExpandable",
		last: "last",
		hitarea: "hitarea"
	};
	
	// provide backwards compability
	$.fn.Treeview = $.fn.treeview;
	
})(jQuery);